package com.example.everying.aspect;

import com.example.everying.annotation.WebLog;
import com.example.everying.utils.MyObjectMapperUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: everything
 * @description: AOP日志
 * @author: zw
 * @create: 2025-06-04 18:18
 **/
@Aspect
@Component
@Slf4j
public class WebLogAspect {

    @Pointcut("@annotation(com.example.everying.annotation.WebLog)")
    public void webLog() {}

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        // 获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录请求信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        WebLog webLog = method.getAnnotation(WebLog.class);

        Map<String, Object> logMap = new HashMap<>();
        logMap.put("url", request.getRequestURL().toString());
        logMap.put("method", request.getMethod());
        logMap.put("ip", request.getRemoteAddr());
        logMap.put("classMethod", signature.getDeclaringTypeName() + "." + signature.getName());
        logMap.put("description", webLog.description());
        try {
            logMap.put("args", MyObjectMapperUtil.getObjectMapper().writeValueAsString(joinPoint.getArgs()));
        }catch (Exception e){
            log.warn("Failed  to serialize args: {}", Arrays.toString(joinPoint.getArgs()));
        }


        log.info("====== Request Info ======\n{}", MyObjectMapperUtil.getObjectMapper().writeValueAsString(logMap));

        // 执行目标方法
        Object result = joinPoint.proceed();

        // 记录响应信息
        long endTime = System.currentTimeMillis();
        log.info("====== Response Info ======");
        log.info("Response result: {}", MyObjectMapperUtil.getObjectMapper().writeValueAsString(result));
        log.info("Time consumed: {} ms", endTime - startTime);

        return result;
    }

}
